package at.codebase.web.util.api;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;

import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import at.codebase.core.log.Log;
import at.codebase.db.entities.EApiPartner;
import at.codebase.db.entities.EItem;
import at.codebase.db.entities.EItemFeedback.EItemFeedbackRating;
import at.codebase.db.entities.EMessageExt;

import com.google.appengine.api.urlfetch.FetchOptions;
import com.google.appengine.api.urlfetch.HTTPHeader;
import com.google.appengine.api.urlfetch.HTTPMethod;
import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;
import com.google.appengine.labs.repackaged.org.json.JSONArray;

public class ApiPartnerCalls {
	
	public static JSONObject submitItemRating(EApiPartner partner, String itemId, String username,
			Long userId, EItemFeedbackRating feedbackRating, String feedbackText,
			Long fbId) {
		Float f;
		switch(feedbackRating) {
		case NO_RATING: f = new Float(0);
			break;
		case RUBY_1: f = new Float(1);
			break;
		case RUBY_2: f = new Float(2);
			break;
		case RUBY_3: f = new Float(3);
			break;
		case RUBY_4: f = new Float(4);
			break;
		case RUBY_5: f = new Float(5);
			break;
		default: f = new Float(0);
			break;
		}
		String params = "target_item_id=" + itemId +
				"&user_name=" + username +
				"&user_id=" + userId +
				"&rating=" + f.toString() +
				"&feedback=" + feedbackText +
				"&feedback_id=" + fbId.toString();
		String result = makeApiCall(partner, "/webservices/add_item_rating", params, "POST");
		JSONObject jsonResult = (JSONObject) JSONValue.parse(result);
		System.out.println("response: " + jsonResult);
		return  jsonResult;
	}
	
	public static JSONObject sendMessage(EApiPartner partner, EMessageExt outgoingMessage){
		String call = "";
		if(!outgoingMessage.isPm()){
			call += "&item_id="+outgoingMessage.getItem();	
		}
		
		call += "&source_user_id="+outgoingMessage.getAddressor().get().getId();
		call += "&source_user_name="+outgoingMessage.getAddressor().get().getUsername();
		call += "&destination_user_id="+outgoingMessage.getRecipientExt().getUserId();
		call += "&subject=";
		call += "&message="+outgoingMessage.getText();
		call += "&source_conversation_id=0";
		call += "&destination_conversation_id="+outgoingMessage.getConversationId();
		
		String result = makeApiCall(partner, "/webservices/send_message", call, "POST");
		JSONObject jsonResult = (JSONObject) JSONValue.parse(result);
		return  jsonResult;
	}
	
	public static JSONObject getItem(EApiPartner partner, String itemId) {
		String call = "";
		
		call += "&item_id="+itemId;

		String result = makeApiCall(partner, "/webservices/item", call, "GET");
		JSONObject jsonResult = (JSONObject) JSONValue.parse(result);
		return  jsonResult;
	}
	
	@SuppressWarnings("unchecked")
	private static boolean sendNewItem(EApiPartner partner, EItem item, String serverUrl){
		String call = "";
		JSONArray items = new JSONArray();
		
		JSONObject itemObj = new JSONObject();
		itemObj.put("id", item.getId());
		itemObj.put("title", item.getTitle());
		itemObj.put("description", item.getDescription());
			JSONObject sellerObj = new JSONObject();
			sellerObj.put("id", item.getSeller().get().getId());
			sellerObj.put("username", item.getSeller().get().getUsername());
		itemObj.put("seller", sellerObj);
		itemObj.put("image", "image");
		itemObj.put("price", item.getPrice()+" USD");
		itemObj.put("url", serverUrl+"/items/"+item.getId());
		
		items.put(itemObj);
		
		call += "&data="+items.toString();
		String result = makeApiCall(partner, "/webservices/new_item", call, "POST");
		JSONObject jsonResult = (JSONObject) JSONValue.parse(result);
		if(jsonResult != null && jsonResult.get("success").equals(new Boolean(true))){
			return true;
		}else{
			return false;
		}
	}

	public static JSONObject getSearchSuggestions(EApiPartner partner, String query) {
		String call = "";
		
		call += "&query="+query;

		String result = makeApiCall(partner, "/webservices/search_suggestions", call, "GET");
		JSONObject jsonResult = (JSONObject) JSONValue.parse(result);
		return  jsonResult;
	}
	
	public static void notifyAboutNewItem(EItem item, String serverUrl) {
		List<EApiPartner> partners = EApiPartner.getAllPartners();
		for(EApiPartner p:partners){
			if(sendNewItem(p, item, serverUrl)){
				Log.logItem(new Long(item.getSeller().getKey().getId()), "Successfully notified " + p.getAppName()
						+ " about new item (itemid=" + item.getId() + ")");
			}else{
				Log.logItem(new Long(item.getSeller().getKey().getId()), "Unsuccessfully notified " + p.getAppName()
						+ " about new item (itemid=" + item.getId() + ")");
			}
		}
	}
	

	public static Map<EApiPartner, String> makeApiCalls(
			List<EApiPartner> partners, String context, String params, String method) {
		Map<EApiPartner, String> results = new HashMap<EApiPartner, String>();
		for (EApiPartner eApiPartner : partners) {
			results.put(eApiPartner, makeApiCall(eApiPartner, context, params,method));
		}
		return results;
	}

	public static String makeApiCall(EApiPartner eApiPartner, String context, String params, String method) {
		StringBuilder builder = new StringBuilder();
		try {
			if(method.equals("GET")) {
				params = "?" + params;
				params += "&auth_token=" + eApiPartner.getAccessToken();
				context = context + params;
			}
			URL url = new URL(eApiPartner.getAppUrl() + context);
			HttpURLConnection connection = (HttpURLConnection) url
					.openConnection();
			connection.setRequestMethod(method);
			connection.setRequestProperty("Accept-Charset", "UTF-8");
			connection.setRequestProperty("Accept", "application/json");
			if(method.equals("POST")) {
				params += "&auth_token=" + eApiPartner.getAccessToken();
				connection.setRequestProperty("Content-Length", String.valueOf(params.length()));
				connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
				connection.setDoOutput(true);
				connection.setDoInput(true);
				connection.setUseCaches(false);
				OutputStreamWriter writer = new OutputStreamWriter( connection.getOutputStream() );
				writer.write(params);
				writer.flush();
				writer.close();
			}
			
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					connection.getInputStream()));
			String line;
			while ((line = reader.readLine()) != null) {
				builder.append(line);
			}
			reader.close();
		} catch (MalformedURLException e) {
		} catch (IOException e) {
		}
		return builder.toString();
	}

	public static Future<HTTPResponse> makeAsyncApiCall(
			EApiPartner eApiPartner, String context, String params) {
		try {
			URL url = new URL(eApiPartner.getAppUrl() + context);
			HTTPRequest request = new HTTPRequest(url, HTTPMethod.POST,
					FetchOptions.Builder.validateCertificate());
			request.setHeader(new HTTPHeader("Accept-Charset", "UTF-8"));
			request.setHeader(new HTTPHeader("Accept", "application/json"));
			params += "&auth_token=" + eApiPartner.getAccessToken();
			HttpURLConnection connection = (HttpURLConnection) url
					.openConnection();
			connection.setDoInput(true);
			connection.setDoOutput(true);
			connection.setUseCaches(false);
			connection.setRequestProperty("Content-Length", String.valueOf(params.length()));
			connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			
			OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
			writer.write(params);
			writer.flush();
			writer.close();
			
			return URLFetchServiceFactory.getURLFetchService().fetchAsync(
					request);
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			System.out.println("e: " + e.getMessage());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("e: " + e.getMessage());
		}
		return null;
	}

	public static Map<EApiPartner, Future<HTTPResponse>> makeAsyncApiCall(List<EApiPartner> eApiPartners,
			String context, String params) {
		Map<EApiPartner, Future<HTTPResponse>> m = new HashMap<EApiPartner, Future<HTTPResponse>>();
		for (EApiPartner eApiPartner : eApiPartners) {
			m.put(eApiPartner, makeAsyncApiCall(eApiPartner, context, params));
		}
		return m;
	}

}
